home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / gfx / show / jpegAGAsrc21.lha / jpegAGAsrc / ppm2AGA / ppmlib.c < prev    next >
C/C++ Source or Header  |  1994-09-25  |  15KB  |  604 lines

  1. /* pbm utility library
  2. **
  3. ** Copyright (C) 1988 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. /* modified by Günther Röhrich */
  14. /* WARNING: This file is not for use with normal pbm programs */
  15.  
  16. /* support functions for the ppm stuff */
  17.  
  18. #include <stdarg.h>
  19. #include "ppm.h"
  20. #include "ppm2AGA.h"
  21. #include "libpbm.h"
  22. #include "libppm.h"
  23. #include "libpgm.h"
  24.  
  25. extern jmp_buf ErrorEnv;
  26. static bit pbm_getbit(FILE *);
  27. extern pixel **pixels;
  28. extern int cols;
  29. extern int rows;
  30. extern int rowcnt;
  31. extern pixel *pixrow;
  32. extern pixval maxval;
  33. extern int ppmformat;
  34. extern int ColorRegMax;
  35.  
  36. extern long  *thisrerr;
  37. extern long  *nextrerr;
  38. extern long  *thisgerr;
  39. extern long  *nextgerr;
  40. extern long  *thisberr; 
  41. extern long  *nextberr;     
  42. extern int Convert4096; 
  43. extern int Convert262144;
  44. extern int fs_direction;
  45. #define FS_SCALE 1024
  46.  
  47. void FSrow(pixel *pixelrow, int cols);
  48.  
  49. /* this is called when an error in ppm2ilbm() is found */
  50. void pm_error(char *format, ...)
  51. {
  52.  va_list args;
  53.  va_start(args, format);
  54.  vprintf(format, args); /* modify this if we don't output to stdout any more */
  55.  va_end(args);
  56.  longjmp(ErrorEnv, 10);
  57. }
  58.  
  59. /* this is defined in ppm2AGA.c
  60. void pm_message(char *format, ...)
  61. {
  62.  va_list args;
  63.  va_start(args, format);
  64.  vprintf(format, args); 
  65.  va_end(args);
  66. }
  67. */
  68.  
  69. void ppm_readppminitrest(FILE *file, int *colsP, int *rowsP, pixval *maxvalP)
  70.     {
  71.     int maxval;
  72.  
  73.     /* Read size. */
  74.     *colsP = pbm_getint( file );
  75.     *rowsP = pbm_getint( file );
  76.  
  77.     /* Read maxval. */
  78.     maxval = pbm_getint( file );
  79.     if ( maxval > PPM_MAXMAXVAL )
  80.     pm_error(
  81. "maxval is too large - try reconfiguring with PGM_BIGGRAYS\n\
  82.     or without PPM_PACKCOLORS\n" );
  83.     *maxvalP = maxval;
  84.     }
  85.  
  86. pixval ppm_pbmmaxval = 1;
  87.  
  88. void ppm_readppminit(FILE *file, int *colsP, int *rowsP, 
  89.                      pixval *maxvalP, int *formatP)
  90.     {
  91.     /* Check magic number. */
  92.     *formatP = pbm_readmagicnumber( file );
  93.     switch ( PPM_FORMAT_TYPE(*formatP) )
  94.     {
  95.     case PPM_TYPE:
  96.     ppm_readppminitrest( file, colsP, rowsP, maxvalP );
  97.     break;
  98.  
  99.     case PGM_TYPE:
  100.     pgm_readpgminitrest( file, colsP, rowsP, maxvalP );
  101.     break;
  102.  
  103.     case PBM_TYPE:
  104.     pbm_readpbminitrest( file, colsP, rowsP );
  105.     *maxvalP = ppm_pbmmaxval;
  106.     break;
  107.  
  108.     default:
  109.     pm_error( "bad magic number - not a ppm, pgm, or pbm file\n" );
  110.     }
  111.     }
  112.  
  113.  
  114. char pbm_getc(FILE *file)
  115.     {
  116.     register int ich;
  117.     register char ch;
  118.  
  119.     ich = getc( file );
  120.     if ( ich == EOF )
  121.     pm_error( "EOF / read error\n" );
  122.     ch = (char) ich;
  123.     
  124.     if ( ch == '#' )
  125.     {
  126.     do
  127.         {
  128.         ich = getc( file );
  129.         if ( ich == EOF )
  130.         pm_error( "EOF / read error\n" );
  131.         ch = (char) ich;
  132.         }
  133.     while ( ch != '\n' && ch != '\r' );
  134.     }
  135.  
  136.     return ch;
  137.     }
  138.  
  139. unsigned char pbm_getrawbyte(FILE *file)
  140.     {
  141.     register int iby;
  142.  
  143.     iby = getc( file );
  144.     if ( iby == EOF )
  145.     pm_error( "EOF / read error\n" );
  146.     return (unsigned char) iby;
  147.     }
  148.  
  149. int pbm_getint(FILE *file)
  150.     {
  151.     register char ch;
  152.     register int i;
  153.  
  154.     do
  155.     {
  156.     ch = pbm_getc( file );
  157.     }
  158.     while ( ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' );
  159.  
  160.     if ( ch < '0' || ch > '9' )
  161.     pm_error( "junk in file where an integer should be\n" );
  162.  
  163.     i = 0;
  164.     do
  165.     {
  166.     i = i * 10 + ch - '0';
  167.     ch = pbm_getc( file );
  168.         }
  169.     while ( ch >= '0' && ch <= '9' );
  170.  
  171.     return i;
  172.     }
  173.  
  174. int pbm_readmagicnumber(FILE *file)
  175.     {
  176.     int ich1, ich2;
  177.  
  178.     ich1 = getc( file );
  179.     if ( ich1 == EOF )
  180.     pm_error( "EOF / read error reading magic number\n" );
  181.     ich2 = getc( file );
  182.     if ( ich2 == EOF )
  183.     pm_error( "EOF / read error reading magic number\n" );
  184.     return ich1 * 256 + ich2;
  185.     }
  186.  
  187.  
  188. void pbm_readpbminitrest(FILE *file, int *colsP, int *rowsP ) 
  189.     {
  190.     /* Read size. */
  191.     *colsP = pbm_getint( file );
  192.     *rowsP = pbm_getint( file );
  193.     }
  194.  
  195. void pgm_readpgminitrest(FILE *file, int *colsP, int *rowsP, gray *maxvalP)
  196.     {
  197.     int maxval;
  198.  
  199.     /* Read size. */
  200.     *colsP = pbm_getint( file );
  201.     *rowsP = pbm_getint( file );
  202.  
  203.     /* Read maxval. */
  204.     maxval = pbm_getint( file );
  205.     if ( maxval > PGM_MAXMAXVAL )
  206.     pm_error( "maxval is too large - try reconfiguring with PGM_BIGGRAYS\n" );
  207.     *maxvalP = maxval;
  208.     }
  209.  
  210. /* Variable-sized arrays. */
  211.  
  212. char*
  213. pm_allocrow( cols, size )
  214.     int cols;
  215.     int size;
  216.     {
  217.     register char* itrow;
  218.  
  219.     itrow = (char*) malloc( cols * size );
  220.     if ( itrow == (char*) 0 )
  221.         pm_error( "out of memory allocating a row\n" );
  222.     return itrow;
  223.     }
  224.  
  225. void
  226. pm_freerow( itrow )
  227.     char* itrow;
  228.     {
  229.     free( itrow );
  230.     }
  231.  
  232. char**
  233. pm_allocarray( cols, rows, size )
  234.     int cols, rows;
  235.     int size;
  236.     {
  237.     char** its;
  238.     int i;
  239.     its = (char**) malloc( (rows + 1) * sizeof(char*) );
  240.     if ( its == (char**) 0 )
  241.         pm_error( "out of memory allocating an array\n" );
  242.  
  243.     /* initialize the array, modified by Günther Röhrich         */
  244.     /* this is needed for using pm_freearray() even if the array */
  245.     /* is not completely allocated                               */
  246.  
  247.     memset((void *)its, 0, (rows + 1) * sizeof(char*));
  248.  
  249.     its[rows] = its[0] = (char*) malloc( rows * cols * size );
  250.     if ( its[0] != (char*) 0 )
  251.         for ( i = 1; i < rows; ++i )
  252.             its[i] = &(its[0][i * cols * size]);
  253.     else
  254.         for( i = 0; i < rows; ++i )
  255.         {
  256.            /* modified by Günther Röhrich */
  257.            if(!(its[i] = (char*) malloc( cols * size )))
  258.            {
  259.              pm_freearray(its, rows);
  260.              its = NULL;
  261.              break;
  262.             }
  263.          }
  264.     return its;
  265.     }
  266.  
  267. void
  268. pm_freearray( its, rows )
  269.     char** its;
  270.     int rows;
  271.     {
  272.     int i;
  273.     if( its[rows] != (char*) 0 )
  274.         free( its[rows] );
  275.     else
  276.         for( i = 0; i < rows; ++i )
  277.             pm_freerow( its[i] );
  278.     free( its );
  279.     }
  280.  
  281. void ppm_readppmrow(FILE* file, pixel* pixelrow, int cols, pixval maxval, int format)
  282.     {
  283.     register int col;
  284.     register pixel* pP;
  285.     register pixval r, g, b;
  286.     gray* grayrow;
  287.     register gray* gP;
  288.     bit* bitrow;
  289.     register bit* bP;
  290.  
  291.     switch ( format )
  292.     {
  293.     case PPM_FORMAT:
  294.       
  295.             for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
  296.         {
  297.         r = pbm_getint( file );
  298. #ifdef DEBUG
  299.         if ( r > maxval )
  300.         pm_error( "r value out of bounds (%u > %u)\n", r, maxval );
  301. #endif /*DEBUG*/
  302.         g = pbm_getint( file );
  303. #ifdef DEBUG
  304.         if ( g > maxval )
  305.         pm_error( "g value out of bounds (%u > %u)\n", g, maxval );
  306. #endif /*DEBUG*/
  307.         b = pbm_getint( file );
  308. #ifdef DEBUG
  309.         if ( b > maxval )
  310.         pm_error( "b value out of bounds (%u > %u)\n", b, maxval );
  311. #endif /*DEBUG*/
  312.         PPM_ASSIGN( *pP, r, g, b );
  313.         }  
  314.          if(Convert4096 || Convert262144) FSrow(pixelrow, cols);    
  315.          break;    
  316.  
  317.     case RPPM_FORMAT:
  318.     for ( col = 0, pP = pixelrow; col < cols; ++col, ++pP )
  319.         {
  320.         r = pbm_getrawbyte( file );
  321. #ifdef DEBUG
  322.         if ( r > maxval )
  323.         pm_error( "r value out of bounds (%u > %u)\n", r, maxval );
  324. #endif /*DEBUG*/
  325.         g = pbm_getrawbyte( file );
  326. #ifdef DEBUG
  327.         if ( g > maxval )
  328.         pm_error( "g value out of bounds (%u > %u)\n", g, maxval );
  329. #endif /*DEBUG*/
  330.         b = pbm_getrawbyte( file );
  331. #ifdef DEBUG
  332.         if ( b > maxval )
  333.         pm_error( "b value out of bounds (%u > %u)\n", b, maxval );
  334. #endif /*DEBUG*/
  335.         PPM_ASSIGN( *pP, r, g, b );
  336.         }
  337.         if(Convert4096 || Convert262144) FSrow(pixelrow, cols);
  338.     break;
  339.  
  340.     case PGM_FORMAT:
  341.     case RPGM_FORMAT:
  342.     grayrow = pgm_allocrow( cols );
  343.     pgm_readpgmrow( file, grayrow, cols, maxval, format );
  344.     for ( col = 0, gP = grayrow, pP = pixelrow; col < cols; ++col, ++gP, ++pP )
  345.         {
  346.         r = *gP;
  347.         PPM_ASSIGN( *pP, r, r, r );
  348.         }
  349.     pgm_freerow( grayrow );
  350.     break;
  351.  
  352.     case PBM_FORMAT:
  353.     case RPBM_FORMAT:
  354.     bitrow = pbm_allocrow( cols );
  355.     pbm_readpbmrow( file, bitrow, cols, format );
  356.     for ( col = 0, bP = bitrow, pP = pixelrow; col < cols; ++col, ++bP, ++pP )
  357.         {
  358.         r = ( *bP == PBM_WHITE ) ? maxval : 0;
  359.         PPM_ASSIGN( *pP, r, r, r );
  360.         }
  361.     pbm_freerow( bitrow );
  362.     break;
  363.  
  364.     default:
  365.     pm_error( "can't happen\n" );
  366.     }
  367.     }
  368.  
  369.  
  370. /* converts one row from 16M colors to 4096/262144 colors using FS dithering */
  371.  
  372. void FSrow(pixel *pixelrow, int cols)
  373.          {
  374.  
  375.            /* if floyd is nonzero we will use Floyd-Steinberg dithering */
  376.            register int col, limitcol;
  377.            register long sg, sr, sb, err;
  378.            long *temperr;
  379.            register pixel *pP;
  380.              
  381.            for ( col = 0; col < cols + 2; ++col )
  382.              nextrerr[col] = nextgerr[col] = nextberr[col] = 0;
  383.  
  384.            if ( fs_direction )
  385.            {
  386.              col = 0;
  387.              limitcol = cols;
  388.              /* pP = pixels[row]; */
  389.              pP = pixelrow;
  390.            }
  391.            else
  392.            {
  393.             col = cols - 1;
  394.             limitcol = -1;
  395.             /* pP = &(pixels[row][col]); */
  396.             pP = &pixelrow[col];
  397.        }
  398.  
  399.            do
  400.            {
  401.              /* Use Floyd-Steinberg errors to adjust actual color. */
  402.              sr = PPM_GETR(*pP) + thisrerr[col + 1] / FS_SCALE;
  403.              sg = PPM_GETG(*pP) + thisgerr[col + 1] / FS_SCALE;
  404.              sb = PPM_GETB(*pP) + thisberr[col + 1] / FS_SCALE;
  405.              if ( sr < 0 ) sr = 0;
  406.              else if ( sr > maxval ) sr = maxval;
  407.              if ( sg < 0 ) sg = 0;
  408.              else if ( sg > maxval ) sg = maxval;
  409.              if ( sb < 0 ) sb = 0;
  410.              else if ( sb > maxval ) sb = maxval;
  411.              /* PPM_ASSIGN( *pP, sr, sg, sb ); */
  412.              if(Convert4096)
  413.                PPM_ASSIGN(*pP, sr&0xF0, sg&0xF0, sb&0xF0);          
  414.              else
  415.                PPM_ASSIGN(*pP, sr&0xFC, sg&0xFC, sb&0xFC);
  416.            
  417.              /* Propagate Floyd-Steinberg error terms. */
  418.              if ( fs_direction )
  419.              {
  420.                err = ( sr - (long) PPM_GETR(*pP) ) * FS_SCALE; 
  421.                thisrerr[col + 2] += ( err * 7 ) / 16;
  422.                nextrerr[col    ] += ( err * 3 ) / 16;
  423.                nextrerr[col + 1] += ( err * 5 ) / 16;
  424.                nextrerr[col + 2] += ( err     ) / 16;
  425.                err = ( sg - (long) PPM_GETG(*pP) ) * FS_SCALE;
  426.                thisgerr[col + 2] += ( err * 7 ) / 16;
  427.                nextgerr[col    ] += ( err * 3 ) / 16;
  428.                nextgerr[col + 1] += ( err * 5 ) / 16;
  429.                nextgerr[col + 2] += ( err     ) / 16;
  430.                err = ( sb - (long) PPM_GETB(*pP) ) * FS_SCALE;
  431.                thisberr[col + 2] += ( err * 7 ) / 16;
  432.                nextberr[col    ] += ( err * 3 ) / 16;
  433.                nextberr[col + 1] += ( err * 5 ) / 16;
  434.                nextberr[col + 2] += ( err     ) / 16;
  435.              }
  436.              else
  437.              {
  438.                err = ( sr - (long) PPM_GETR(*pP) ) * FS_SCALE;
  439.                thisrerr[col    ] += ( err * 7 ) / 16;
  440.                nextrerr[col + 2] += ( err * 3 ) / 16;
  441.                nextrerr[col + 1] += ( err * 5 ) / 16;
  442.                nextrerr[col    ] += ( err     ) / 16;
  443.                err = ( sg - (long) PPM_GETG(*pP) ) * FS_SCALE;
  444.                thisgerr[col    ] += ( err * 7 ) / 16;
  445.                nextgerr[col + 2] += ( err * 3 ) / 16;
  446.                nextgerr[col + 1] += ( err * 5 ) / 16;
  447.                nextgerr[col    ] += ( err     ) / 16;
  448.                err = ( sb - (long) PPM_GETB(*pP) ) * FS_SCALE;
  449.                thisberr[col    ] += ( err * 7 ) / 16;
  450.                nextberr[col + 2] += ( err * 3 ) / 16;
  451.                nextberr[col + 1] += ( err * 5 ) / 16;
  452.                nextberr[col    ] += ( err     ) / 16;
  453.              }
  454.            
  455.              if ( fs_direction )
  456.              {
  457.                ++col;
  458.                ++pP;
  459.              }
  460.              else
  461.              {
  462.                --col;
  463.                --pP;
  464.              }
  465.            } while ( col != limitcol );      
  466.          
  467.            temperr = thisrerr;
  468.            thisrerr = nextrerr;
  469.            nextrerr = temperr;
  470.            temperr = thisgerr;
  471.            thisgerr = nextgerr;
  472.            nextgerr = temperr;
  473.            temperr = thisberr;
  474.            thisberr = nextberr;
  475.            nextberr = temperr;
  476.            fs_direction = ! fs_direction;
  477.          }                  
  478.  
  479.  
  480.  
  481.  
  482. void pgm_readpgmrow(FILE* file, gray* grayrow, int cols, gray maxval, int format)
  483.     {
  484.     register int col;
  485.     register gray* gP;
  486.     bit* bitrow;
  487.     register bit* bP;
  488.  
  489.     switch ( format )
  490.     {
  491.     case PGM_FORMAT:
  492.     for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
  493.         {
  494.         *gP = pbm_getint( file );
  495. #ifdef DEBUG
  496.         if ( *gP > maxval )
  497.         pm_error( "value out of bounds (%u > %u)\n", *gP, maxval );
  498. #endif /*DEBUG*/
  499.         }
  500.     break;
  501.     
  502.     case RPGM_FORMAT:
  503.     for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
  504.         {
  505.         *gP = pbm_getrawbyte( file );
  506. #ifdef DEBUG
  507.         if ( *gP > maxval )
  508.         pm_error( "value out of bounds (%u > %u)\n", *gP, maxval );
  509. #endif /*DEBUG*/
  510.         }
  511.     break;
  512.     
  513.     case PBM_FORMAT:
  514.     case RPBM_FORMAT:
  515.     bitrow = pbm_allocrow( cols );
  516.     pbm_readpbmrow( file, bitrow, cols, format );
  517.     for ( col = 0, gP = grayrow, bP = bitrow; col < cols; ++col, ++gP, ++bP )
  518.         *gP = ( *bP == PBM_WHITE ) ? maxval : 0;
  519.     pbm_freerow( bitrow );
  520.     break;
  521.  
  522.     default:
  523.     pm_error( "can't happen\n" );
  524.     }
  525.     }
  526.  
  527. void pbm_readpbmrow(FILE *file, bit *bitrow, int cols, int format )
  528.     {
  529.     register int col, bitshift;
  530.     register unsigned char item;
  531.     register bit* bP;
  532.  
  533.     switch ( format )
  534.     {
  535.     case PBM_FORMAT:
  536.     for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
  537.         *bP = pbm_getbit( file );
  538.     break;
  539.  
  540.     case RPBM_FORMAT:
  541.     bitshift = -1;
  542.     for ( col = 0, bP = bitrow; col < cols; ++col, ++bP )
  543.         {
  544.         if ( bitshift == -1 )
  545.         {
  546.         item = pbm_getrawbyte( file );
  547.         bitshift = 7;
  548.         }
  549.         *bP = ( item >> bitshift ) & 1;
  550.         --bitshift;
  551.         }
  552.     break;
  553.  
  554.     default:
  555.     pm_error( "can't happen\n" );
  556.     }
  557.     }
  558.  
  559. static bit pbm_getbit(FILE *file )
  560.     {
  561.     register char ch;
  562.  
  563.     do
  564.     {
  565.     ch = pbm_getc( file );
  566.     }
  567.     while ( ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' );
  568.  
  569.     if ( ch != '0' && ch != '1' )
  570.     pm_error( "junk in file where bits should be\n" );
  571.  
  572.     return ( ch == '1' ) ? 1 : 0;
  573.     }
  574.  
  575.  
  576. pixel *next_pixrow(FILE *fp, int row, int ColorShift)
  577. {
  578.   int i;
  579.   pixel *pP;
  580.  
  581.     if( pixels )
  582.         pixrow = pixels[row];
  583.     else {
  584.         if( row != rowcnt )
  585.             pm_error("big mistake\n");
  586.         rowcnt++;
  587.         ppm_readppmrow(fp, pixrow, cols, maxval, ppmformat);
  588.         if(maxval == 255)
  589.         {
  590.           for(i=0,pP=pixrow; i<cols; i++,pP++)
  591.           {
  592.             pP->r = pP->r >> ColorShift;
  593.             pP->g = pP->g >> ColorShift;
  594.             pP->b = pP->b >> ColorShift;
  595.           }
  596.         }
  597.         else
  598.         { 
  599.           for(i=0,pP=pixrow; i<cols; i++,pP++) PPM_DEPTH(*pP, *pP, maxval, ColorRegMax);
  600.         } 
  601.     }
  602.     return pixrow;
  603. }
  604.